Philip Withnall [Tue, 11 Nov 2025 15:31:22 +0000 (15:31 +0000)]
timeLimitsManager: Batch-submit usage records to malcontent-timerd
This was skipped in the first version of parental controls screen time
limits, because we forgot that `RecordUsage()` already allows batch
submission of usage records.
Rework the code to make one D-Bus call rather than O(N) calls.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3958>
The LongPressGesture 'may-recognize' callback in commit 314137c8c was
checking if clicks were inside '_switcherList', but thumbnails shown by
switch-group are siblings of _switcherList, not children.
This caused the gesture to incorrectly identify thumbnail clicks as
'outside' clicks, closing the popup before the click could complete.
Fix by adding a _isActorOutside() helper method that subclasses can
override to check additional containers. AppSwitcherPopup now properly
checks both _switcherList and _thumbnails.
Tested on Ubuntu 25.10 with GNOME Shell 49.0. Confirmed:
- switch-group mouse clicks now work
- switch-applications and switch-windows unaffected
- clicking outside the popup still closes it correctly
- no regressions introduced
Fixes: 314137c8c9 ("switcherPopup: Move to a ClutterGesture for closing the popup") Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/8812
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3959>
Adrian Vovk [Thu, 1 May 2025 22:34:52 +0000 (18:34 -0400)]
main: Register session with GDM on startup
When no monitor is connected, gnome-shell starts but never emits
`startup-prepared` nor `startup-complete`. As a result, GDM never
detects that the shell has launched and plymouthd remains running,
preventing the system from reaching graphical.target.
Ensure that registerSessionWithGDM() is called even when no monitor
is connected, so GDM can terminate plymouthd and allow the system to
reach graphical.target properly.
Part of https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/285
timeLimitsManager: Integrate with malcontent and lock when limit reached
Lock the screen when screen time limit is reached in a child session,
which required extending the existing TimeLimitsManager functionality to
include the parental controls session limits.
TimeLimitsDispatcher was also adjusted to take into account parental
controls session limits before making any user facing changes.
timeLimitsManager: Rename function updating state machine
Rename _updateSettings function to _updateStateMachine, since that's
what the function actually does, starting or stopping the machine
depending on the 'history-enabled' GSetting. Moreover, in the future
we'll take into account parental controls settings too, so renaming the
function to be more generic will avoid confusion later on.
tests/unit: Add a helper method in TimeLimitsManager
Currently we create a new `TimeLimitsManager` for each of the unit tests
for testing the wellbeing screen time limit, with the same parameters.
Rather than having to repeat the entire constructor call multiple times,
factor it out into a helper method on the `TestHarness`. There is no
difference in functionality itself.
Add org.freedesktop.MalcontentTimer1.Child interface for accessing the
screen time and app usage periods for current user account. Currently
unused, will provide necessary functionality when integrating parental
controls session limits with TimeLimitsManager.
parentalControlsManager: Add support for session limits
Add ability to check if session limits are enabled for users using API
introduced in malcontent 0.14.0. The `get_session_limits_async` function
is actually available since 0.5.0, but the signal
`session-limits-changed` was only introduced in 0.14.0, so check for
function `get_daily_limit` which was introduced in 0.14.0 to be sure
we're using correct version. This allows us to keep filtering apps, even
if the library version doesn't fully support session limits.
Will be used in the future to integrate parental controls session
limits.
Carlos Garnacho [Wed, 8 Oct 2025 18:36:39 +0000 (20:36 +0200)]
grabHelper: Port to using ClickGesture to dismiss
There's a few things we don't need anymore here. We don't
need holding on the captured events until button release
anymore, and we don't need to track crossing events outside
the grab as those will not get emitted as usual. This allows
for a few simplifications in handling the events for the
GrabHelper.
Carlos Garnacho [Wed, 8 Oct 2025 17:37:04 +0000 (19:37 +0200)]
searchController: Maybe reset search using a click gesture
We don't want the gesture to consume input though, we just want
it as a trigger on click, so use the ::may-recognize signal to
hook this "reset, but passthrough" behavior on.
We are currently still using eslint 8.x which has been unsupported
for quite a while. Update the ci-run-eslint script to a verison
that uses the supported eslint 9.x.
There's no reason why this is not the case, given that these tests are
running in completely separated environments, so they are safe to run in
parallel
overviewControls: Disconnect signals on destruction
While we are not getting errors and the ControlsManger is normally always
alive, during destruction we could still get events from other objects
that are still alive, so disconnect them all
workspaceThumbnail: Track later hiding drop placeholder
When closing the shell during a relayout we are getting this error:
(gnome-shell:2559407): Gjs-CRITICAL **: 06:57:21.765: Object St.Bin,
has been already disposed — impossible to access it.
This might be caused by the object having been destroyed from C code
using something such as destroy(), dispose(), or remove() vfuncs.
== Stack trace for context 0x60991609b710 ==
#0 b resource:///org/gnome/shell/ui/workspaceThumbnail.js:1334 (5e050636fb0 @ 17)
#1 i resource:///org/gnome/shell/ui/main.js:279 (30c932d102e0 @ 119)
This is because the later we added is running even when not needed (e.g
when the placeholder is not visible already), but also because we may
run the later callback after the parent has been destroyed.
While it only starts the shell, waits for startup being completed and
return, it's relevant to check the shutdown process in this phase and
to ensure that we cleanup things as expected
We (I) changed the test job to use a different path in commit 342d7ab34,
but the artifacts path was not adjusted :(
Fixes: 342d7ab34a ("ci: Start with a fresh build dir to ensure test dependencies are correct")
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3945>
Sebastian Wick [Mon, 20 Oct 2025 11:38:37 +0000 (13:38 +0200)]
brightnessManager: Use slider as bias when auto brightness is being used
The code previously tried to ensure that the sliders were disabled when
auto brightness was active, and determine the brightness just from the
auto brightness target we get from g-s-d.
It turns out that users do want to still have some control over the
brightness, even if auto brightness is active.
The slider is now being used as a bias for the auto brightness target
instead.
This also means that we can drop the BrightnessScale::locked property.
Sebastian Wick [Thu, 30 Oct 2025 10:43:19 +0000 (11:43 +0100)]
brightnessManager: Propagate any attempted brightness change
The BrightnessScale was trying to be smart by not notifying changes of
its value when an action on it (stepUp, stepDown, cycleUp, set value)
resulted in no change.
It turns out that users do want to see an OSD even when their action
resulted in no change.
Alessandro Bono [Thu, 30 Oct 2025 10:47:17 +0000 (11:47 +0100)]
loginManager: Use systemd session auto object to get session ID
Relying on the Display property is buggy when the gdm user spawns more than
one gnome-shell instance.
```
$ loginctl
SESSION UID USER SEAT LEADER CLASS TTY IDLE SINCE
11 42 gdm - 11778 manager-early - no -
c20 42 gdm seat0 34313 greeter tty1 yes 17h ago
c21 42 gdm - 34938 greeter - no -
c22 42 gdm - 35693 greeter - no -
```
From the logs:
```
$ journalctl -b | grep "Will monitor"
[...]
Oct 29 15:14:59 gnome-shell[34961]: Will monitor session c20
Oct 29 15:22:57 gnome-shell[35716]: Will monitor session c20
Oct 29 15:22:58 gnome-shell[35716]: Will monitor session c20
```
Use the systemd session auto object for getting the session id. We can't return
directly the session proxy created from it because it won't emit signals. From
the documentation[1]:
```
Signals are only emitted on objects referencing a specific session ID not on the
"/org/freedesktop/login1/session/self" or "/org/freedesktop/login1/session/auto"
convenience objects, as they can only be dereferenced relative to a method caller.
```
Sebastian Keller [Wed, 29 Oct 2025 10:09:02 +0000 (11:09 +0100)]
osk-layouts: Drop comma key from de-extended and at-extended layouts
The row containing that key was one key too long, which was causing
misalignment. The comma key is not shown in the us-extended layout
either and is available via long press on the dot key or via ?123,
making it the best candidate to remove from these layouts.
This is not needed anymore now that e8d73262 has been reverted and it
was causing problems in X11 sessions, such as when switching from the
4th layout to the 3rd using the keyboard layout menu.
The commit was causing freezes when changing layouts in some situations
and not all of these were adressed by f643915b, such as when switching
from the 3rd to the 4th layout using a xkb shortcut in the X11 session
with 4 layouts.
It was also breaking the order of switching layouts using modifier-only
xkb shortcuts to switch to the next group, which it caused to advance
multiple groups because of the shortcut being handled via both
_modifiersSwitcher() and _layoutGroupChanged().
Further it was possible for _layoutGroupChanged() to trigger an error
due to the locale layout added by _buildGroupStrings() at the end of the
xkb layout list being accessible via the xkb shortcuts. That layout was
not present in _inputSources, leading to "is" being undefined.
Florian Müllner [Tue, 21 Oct 2025 18:12:59 +0000 (20:12 +0200)]
tools: Symlink node_modules in project root
NPM assumes quite strongly that it manages the project as a
whole and its package/lock files are located in the project
root.
While we somehow managed to keep the npm tooling in a subfolder,
this comes at the cost of breaking imports of additional modules.
This will become relevant when we update eslint to a supported
version, as we want to keep using the `junit` formatter in CI,
which has now been split out into a separate module.
So bite the bullet and make the node_modules folder available in
the project root.
On the plus side, having the node_modules folder in the project
root allows language servers in IDEs/editors to pick it up.
Florian Müllner [Thu, 23 Oct 2025 12:06:08 +0000 (14:06 +0200)]
tools: Pin git node modules
Both changes in the config (like new/changes rules) and the eslint wrapper
(like updating to eslint 9.x) could require changes on the shell side, and
therefore require conscious update rather than randomly breaking the CI.
Carlos Garnacho [Thu, 23 Oct 2025 18:56:10 +0000 (20:56 +0200)]
keyboardManager: Update layout index before keymap
Unfortunately, layouts and keymaps are not considered atomic data
even though they are closely related. Furthermore, these are async
operations that are not immediate to apply, and each of them result
in a plethora of updates down in Mutter (layout group being a subset
of keymaps).
Doing things in the current order, these updates do result in a
feedback loop, since the layout index is not changed altogether with
the keymap, but the keymap update is also seen as a layout change.
Even though it still does result in unnecessary intermediate updates,
changing the layout index first avoids the feedback loop, since it
will already match with the expectations after the ClutterKeymap is
updated.
This fixes deadlocked shell when using xkb options that trigger layout
changes through the ISO_Next_Group key emission, when the group change
also triggered a keymap update (e.g. moving to a different group
per KeyboardManager.MAX_LAYOUTS_PER_GROUP limits).
This does not fix being able to switch between all layouts, when
there is more than one group. This will be fixed in later commits.
Sebastian Keller [Sat, 25 Oct 2025 11:03:55 +0000 (13:03 +0200)]
keyboard: Don't move window when it got unmanaged during shift animation
When a window with a text-entry at the bottom that had triggered the OSK
and was shifted up to avoid overlapping the OSK is closed right after
losing keyboard focus, this results in a crash. The focus loss triggers
the animation to move the window actor back into its original position,
which moves the underlying window when finished. That however will fail
when the window has been unmanaged and some of the underlying resources
have already been destroyed while the animation was playing.
Florian Müllner [Tue, 21 Oct 2025 22:57:26 +0000 (00:57 +0200)]
systemActions: Don't log error when cancelled
If the logout/reboot/shutdown actions are available, we expect them
to succeed. Unfortunately that changed in the light of systemd
inhibitors (that we don't know about in the shell, and that prevent
those actions now).
While it would be good to fix the underlying issue, we can at least
improve the error reporting in that case and not log the error when
the operation was cancelled: We don't know the underlying reason,
unlike gnome-session which should have logged a more helpful message.
Florian Müllner [Fri, 24 Oct 2025 11:39:37 +0000 (13:39 +0200)]
js: Use const declarations where possible
It is useful to indicate clearly that a value is read-only, and
we have already been doing so for new code for a long time. But
in order to actually enforce this, we have to adjust all existing
code.
Luckily the change is trivial enough to do (thanks to `eslint --fix`),
so do it now.
For some reason, installing malcontent with buildah as a proxy, results
in the malcontent-client binary missing the execute permission, even
though manually invoking the install-meson-project.sh script results in
the correct permissions being set.
Work around this by manually setting the correct permissions on the
malcontent-client binary.
The child watch source is the only thing that reaps the child process.
We cannot remove it until it fires or the child will remain a zombie.
So, just leave the source attached. Trying to remove it does not seem
easy, and I don't see any need; we expect the child process to exit
quickly, so this doesn't seem harmful.
Sebastian Keller [Sun, 19 Oct 2025 16:47:31 +0000 (18:47 +0200)]
dnd: Don't try to connect to transition when animations are disabled
When animations are disabled, the ease has finished before the
get_transition() call, causing the latter to return null, which will
result in an error message when connected to.
Antoine Lassagne [Fri, 10 Oct 2025 12:55:40 +0000 (14:55 +0200)]
status/network: Update indicator icon on connectivity changes
When there is no active main connection or it uses a device type we do
not handle, the indicator icon and its visibility depend on the global
connectivity.
However we currently don't update the icon on connectivity changes,
with the result that we sometimes show the fallback connection icon
when the network is in fact disconnected.
To fix this, update the icon whenever the (global) connectivity changes.
Florian Müllner [Thu, 16 Oct 2025 20:48:21 +0000 (22:48 +0200)]
ci: Reinstall gdk-pixbuf2 package
The mutter image contains a custom gdk-pixbuf build without the
glycin loader, in order to unbreak running installed tests in CI.
The downside is that we end up with no SVG loader. For the toolbox
image we don't care about installed tests, but we very much care about
working icons.
So reinstall the distro gdk-pixbuf package to bring back the glycin
loader (and thus SVG support).
Davide Ferracin [Tue, 7 Oct 2025 12:45:45 +0000 (14:45 +0200)]
i18n: Add context to "Power mode" title string
The "Power mode" string in the quick settings menu appears both in the
title of the button and as the menu header that opens when clicking on
such button.
Currently they are translated together, but---at least in
Italian---the standard translation, "Modalità energia", is too long to
fit in the button and is very often truncated to "Modalità…" (aka
"Mode", in English) from which is not clear what the menu is about.
We would use "Energia" for the button title, but at the same time it
would be nice to have the full "Modalità energia" translation in the
menu header, where there is more space available.
For this reason I propose to add contexts to the two "Power mode"
strings, so that the string can be translated in different ways
depending on its position.
Florian Müllner [Wed, 1 Oct 2025 18:19:14 +0000 (20:19 +0200)]
messageList: Make media messages follow notification policy
Unlike regular notifications, media messages are shown unconditionally
for any active MPRIS player. In the past that was uncontroversial, but
now that media messages are shown on the lock screen as well, there is
a privacy concern.
To address this, make media messages follow the notification policy
of the corresponding app (if specified) or the general notification
settings.
messageTray: Never close a notification banner that is about to show
If a new notification is pushed (or the same is updated) in a very short
time GNOME shell may only show the last notification (or none).
This is because since commit 2801d0bf a notification that is about to
show (so in SHOWING state) may be considered expired, given that the
notification timeout won't be set until the show animation has
completed.
Thus, only consider the notification as expired when the notification is
in the shown state, but not in the showing one.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6529 Fixes: 2801d0bfe3 ("messageTray: Close SHOWING banner when its notification is destroyed")
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3905>
notificationDaemon: Do not send activation event multiple times
When a FDO notification is updated we reuse the previous instance,
however we do not care about disconnecting the default activation signal
and thus we may end up emitting the same multiple times, even in the
case the updated notification has no action at all.